package com.github.jameszbl.toolkits

import android.annotation.SuppressLint
import android.annotation.TargetApi
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.Service
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.media.RingtoneManager
import android.os.BatteryManager
import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.preference.PreferenceManager.getDefaultSharedPreferences
import java.time.DayOfWeek.SATURDAY
import java.time.DayOfWeek.SUNDAY
import java.time.LocalDateTime

class AlarmReceiver : BroadcastReceiver() {

    companion object {
        const val CHANNEL_ID = "charge"
    }

    private var mContext: Context? = null

    @TargetApi(Build.VERSION_CODES.M)
    @SuppressLint("UnsafeProtectedBroadcastReceiver")
    override fun onReceive(context: Context?, intent: Intent?) {
        mContext = context
        val batteryManager = mContext?.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
        val power = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
        val charging = batteryManager.isCharging
        val full = threshold() < power
        if (!isAlarmOn() || !isRightTime() || full || charging) {
            return
        }
        notifyChargeAlarm()
    }

    @TargetApi(Build.VERSION_CODES.O)
    private fun isRightTime(): Boolean {
        val now = LocalDateTime.now()
        val hour = now.hour
        val dayOfWeek = now.dayOfWeek
        var start = 18
        var end = 20
        val timeRange = timeRange()
        timeRange?.let {
            start = it.start
            end = it.end
        }
        val alarmAtWeekends = getDefaultSharedPreferences(mContext)
            .getBoolean("charge_alarm_at_weekends", false)
        val isWeekends = SATURDAY == dayOfWeek || SUNDAY == dayOfWeek
        return (!isWeekends || alarmAtWeekends) && hour in start until end
    }

    private fun isAlarmOn(): Boolean = getDefaultSharedPreferences(mContext)
        .getBoolean("charge_alarm", true)

    private fun timeRange(): TimeRange? {
        val start = getDefaultSharedPreferences(mContext)
            .getString("charge_alarm_start_hour", "20")?.toInt() ?: 20
        val end = getDefaultSharedPreferences(mContext)
            .getString("charge_alarm_end_hour", "22")?.toInt() ?: 22
        return TimeRange(start, end)
    }

    private class TimeRange(var start: Int, var end: Int)

    private fun threshold(): Int = getDefaultSharedPreferences(mContext)
        .getString("charge_alarm_power_threshold", "80")?.toInt() ?: 80

    @TargetApi(Build.VERSION_CODES.O)
    private fun notifyChargeAlarm() {
        val intent = Intent(mContext, MainActivity::class.java).apply {
            flags = Intent.FLAG_ACTIVITY_CLEAR_TASK
        }
        val pendingIntent: PendingIntent = PendingIntent.getActivity(mContext, 0, intent, 0)
        val notificationManager: NotificationManager =
            mContext?.getSystemService(Service.NOTIFICATION_SERVICE) as NotificationManager
        val notificationChannel =
            notificationManager.getNotificationChannel(CHANNEL_ID)
        if (null == notificationChannel) {
            val name = "Charge"
            val descriptionText = "Charge Alarm"
            val importance = NotificationManager.IMPORTANCE_DEFAULT
            val channel = NotificationChannel(CHANNEL_ID, name, importance).apply {
                description = descriptionText
            }
            notificationManager.createNotificationChannel(channel)
        }
        val builder = NotificationCompat.Builder(mContext!!, CHANNEL_ID)
            .setSmallIcon(R.mipmap.ic_launcher)
            .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
            .setContentTitle(mContext?.getString(R.string.notification_charge_title))
            .setContentText(mContext?.getString(R.string.notification_charge_content))
            .setPriority(NotificationCompat.PRIORITY_DEFAULT)
            .setContentIntent(pendingIntent)
            .setAutoCancel(true)
        notificationManager.notify(0, builder.build())
    }
}
